﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCore.Common.Authentication.JWT;

namespace WorkFlowCore.Common.Authorization.JWT
{
    public class AuthorizationMiddleware
    {
        private readonly RequestDelegate next;

        public AuthorizationMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(HttpContext context, JWTAuthenticationManager jWTAuthenticationManager, ICustomizationVerify customizationVerify, ICustomizationVerify[] customizationVerifies)
        {
            
            var accessToken = context.Request.Headers["access_token"].ToString();
            if (!string.IsNullOrEmpty(accessToken))
            {
                context.Request.Headers["authorization"] = $"Bearer {accessToken}";
            }

            accessToken = context.Request.Query["access_token"].ToString();
            if (!string.IsNullOrEmpty(accessToken))
            {
                context.Request.Headers["authorization"] = $"Bearer {accessToken}";
            }

            accessToken = context.Request.Headers["authorization"].ToString();

            //var result = await context.AuthenticateAsync();

            if (!jWTAuthenticationManager.TokenValid(accessToken))
            {
                if (!JWTAuthenticationOptions.AuthenticationEnacted)
                {
                    context.Request.Headers["authorization"] = $"Bearer {jWTAuthenticationManager.GenerateDefaultToken()}";
                }
                else
                {
                    var valid = false;
                    if (customizationVerify != null)
                    {
                        var verify = customizationVerify.Verify(new VerifyInput { Context = context, OriginalToken = accessToken });
                        if (verify.IsValid)
                        {
                            valid = true;
                            accessToken = jWTAuthenticationManager.Login(verify.User, verify.Claims);
                            context.Request.Headers["authorization"] = $"Bearer {accessToken}";
                        }
                    }

                    if (!valid && customizationVerifies != null)
                    {
                        foreach (var _customizationVerify in customizationVerifies)
                        {
                            var verify = _customizationVerify.Verify(new VerifyInput { Context = context, OriginalToken = accessToken });
                            if (verify.IsValid)
                            {
                                accessToken = jWTAuthenticationManager.Login(verify.User, verify.Claims);
                                context.Request.Headers["authorization"] = $"Bearer {accessToken}";
                                break;
                            }
                        }

                    }
                    else if (!valid)
                    {
                        context.Request.Headers["authorization"] = string.Empty;
                    }
                }
            }

            await next(context);

            accessToken = context.Request.Headers["authorization"];
            if(context.AuthenticateAsync().Result.Succeeded)
            {
                if(!jWTAuthenticationManager.TokenValid(accessToken))
                {
                    jWTAuthenticationManager.Login(accessToken, string.Empty);
                }
            }
            else
            {
                jWTAuthenticationManager.Logout(string.Empty);
            }

        }
    }
}
